import 'dart:collection' show ListMixin, MapMixin;

import '../data_store/data_store.dart';

part 'states.dart';
part 'list_state.dart';
part 'map_state.dart';
part 'extension.dart';

typedef Updater = Function();
typedef ValueUpdater<T> = Function(T newValue, T oldValue);
typedef SaveCallback = Function(int id);

///可更新超类，存储更新函数列表的混合器
mixin UpdatableMixin {
  final List<Updater> _updaters = [];
  List<Updater> get updaters => _updaters;
  void addUpdater(Updater updater) => _updaters.add(updater);
  void removeUpdater(Updater updater) => _updaters.remove(updater);
  void doUpdate() {
    for (final updater in _updaters) {
      updater();
    }
  }
}

///可更新超类的简单实现代理
class UpdatableProxy with UpdatableMixin {}

///可自动更新状态的超类（混合器）
mixin AbstractState<T> {
  T get value;
  set value(newValue);

  bool get autoUpdate;
  set autoUpdate(bool b);
  void addUpdater(Updater updater);
  void removeUpdater(Updater updater);

  //状态传递
  TransferState<R> toTransferState<R>(R Function(dynamic) transfer) =>
      TransferState(this, transfer);
}

///可自动更新状态的具体实现
class UpdatableState<T> with AbstractState<T>, UpdatableMixin {
  UpdatableState({required T initValue, bool? autoUpdate})
      : _value = initValue,
        _autoUpdate = autoUpdate ?? true;
  bool _autoUpdate;
  T _value;
  @override
  T get value => _value;
  @override
  set value(newValue) {
    if (_value != newValue) {
      _value = newValue;
      if (_autoUpdate) doUpdate();
    }
  }

  @override
  bool get autoUpdate => _autoUpdate;
  @override
  set autoUpdate(bool b) => _autoUpdate = b;
  @override
  String toString() => _value.toString();
}

///组合的状态
class CombineUpdatableState<T> extends UpdatableState<T> {
  CombineUpdatableState(this.states, this.listToValue)
      : super(initValue: listToValue(states)) {
    for (final state in states) {
      state.addUpdater(() => value = listToValue(states));
    }
  }
  final List<AbstractState> states;
  final T Function(List<AbstractState> states) listToValue;
}

///组合的可自动更新列表状态
class CombineUpdatableListState<T> extends UpdatableState<List<T>> {
  CombineUpdatableListState(this.states)
      : super(initValue: states.map((e) => e.value).toList()) {
    for (final state in states) {
      state.addUpdater(() => value = states.map((e) => e.value).toList());
    }
  }
  final List<AbstractState<T>> states;
}

///传递的状态
class TransferState<T> extends UpdatableState<T> {
  final AbstractState state;
  final T Function(dynamic) transfer;

  TransferState(this.state, this.transfer)
      : super(initValue: transfer(state.value)) {
    state.addUpdater(() => value = transfer(state.value));
  }
}

///数据库状态超类
mixin DatabaseMixin {
  Future<int> save([SaveCallback? callback]);
  DatabaseState<T> getDatabaseState<T>(T value, Function(T newValue) updater) {
    DatabaseState<T> databaseState = DatabaseState(value);
    databaseState.addUpdater(() => updater(databaseState.value));
    databaseState._save = save;
    return databaseState;
  }
}

class DatabaseState<T> extends UpdatableState<T> {
  DatabaseState(T initValue) : super(initValue: initValue);
  Function()? _save;
  void initSaveFunction(Function() save) => _save = save;
  @override
  set value(newValue) {
    if (_value != newValue) {
      _value = newValue;
      doUpdate();
      _save?.call();
    }
  }
}

class StorableState<T> extends UpdatableState<T> with StorableMixin {
  StorableState({
    required super.initValue,
    required Object storeKey,
    super.autoUpdate,
    bool? autoSave,
  }) {
    this.storeKey = storeKey;
  }

  final List<ValueUpdater<T>> valueUpdaters = [];
  void addValueUpdater(ValueUpdater<T> updater) => valueUpdaters.add(updater);
  void removeValueUpdater(ValueUpdater<T> updater) =>
      valueUpdaters.remove(updater);

  @override
  void doUpdate() {
    super.doUpdate();
    final newValue = value;
    for (final updater in valueUpdaters) {
      updater(newValue, _oldValue);
    }
  }

  void _update(T newValue) {
    super.doUpdate();
    for (final updater in valueUpdaters) {
      updater(newValue, _oldValue);
    }
  }

  late T _oldValue;

  @override
  set value(newValue) {
    _oldValue = value;
    if (_oldValue != newValue) {
      setNewValue(newValue);
      if (_autoUpdate) _update(newValue);
      putToDataStorer();
    }
  }

  void setNewValue(T newValue) => _value = newValue;

  @override
  void getFromDataStorer() {
    _value = dataStorer?.get<T>(storeKey) ?? _value;
  }

  @override
  Future<void> putToDataStorer() async {
    dataStorer?.put(storeKey, _value);
  }

  @override
  Future<void> delete() async {
    dataStorer?.delete(storeKey);
  }
}

class EnumState<T> extends StorableState<T> {
  EnumState({
    required this.values,
    required super.initValue,
    required super.storeKey,
    super.autoSave,
  }) : _stringValue = initValue.toString() {
    for (var enumValue in values) {
      transferMap[enumValue.toString()] = enumValue;
    }
  }
  String _stringValue;
  final List<T> values;
  final Map<String, T> transferMap = {};

  @override
  void setNewValue(T newValue) {
    _value = newValue;
    _stringValue = newValue.toString();
  }

  @override
  void getFromDataStorer() {
    _stringValue = dataStorer?.get(storeKey) ?? _stringValue;
    _value = transferMap[_stringValue] ?? _value;
  }

  @override
  Future<void> putToDataStorer() async {
    dataStorer?.put(storeKey, _stringValue);
  }

  @override
  String toString() => _stringValue;
}

class CombineState<T> extends StorableState<T> {
  CombineState({
    required this.listToValue,
    required this.valueToList,
    required super.initValue,
    required super.storeKey,
    super.autoSave,
  });
  final T Function(List list) listToValue;
  final List Function(T value) valueToList;

  @override
  void getFromDataStorer() {
    final list = dataStorer?.get<List>(storeKey);
    if (list != null) _value = listToValue(list);
  }

  @override
  Future<void> putToDataStorer() async {
    dataStorer?.put(storeKey, valueToList(_value));
  }
}
